﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Forms;
using System.Diagnostics;


namespace vmMachine
{
    class StateUML : UMLDisplay
    {
        public List<UMLLayer> pics;
        Form1 form;
        VendingMachineLogic vMachine;
        private static System.Windows.Forms.Timer aTimer;
        private static System.Windows.Forms.Timer resetArrowTimer;
        private static System.Windows.Forms.Timer changeArrowTimer;
        private static System.Windows.Forms.Timer yesArrowTimer;
        private static System.Windows.Forms.Timer noArrowTimer;
        public int speed=3000;
        Stopwatch stopWatch;
        bool resetArrow=false;
        bool changeArrow = false;
        bool yesArrow = false;
        bool noArrow = false;



        public StateUML(Form1 aform, VendingMachineLogic v)
        {
            pics = new List<UMLLayer>();
            form = aform;
            vMachine = v;

            //============ Init UML Layers (red arrows/squers) ==============

            UMLLayer disMoneyAmount = new UMLLayer("displayMoneyAmount", form.displayMoneyAmount);
            pics.Add(disMoneyAmount);

            UMLLayer disitemInStock = new UMLLayer("displayItemInStock", form.displayItemInStock);
            pics.Add(disitemInStock);

            UMLLayer disPrice = new UMLLayer("displayPrice", form.displayPrice);
            pics.Add(disPrice);

            UMLLayer disSoldOut = new UMLLayer("displaySoldOut", form.displaySoldOut);
            pics.Add(disSoldOut);

            UMLLayer disDispenseItem = new UMLLayer("displayDispenseItem", form.displayDispenseItem);
            pics.Add(disDispenseItem);

            UMLLayer disCountMoney = new UMLLayer("displayCountMoney", form.displayCountMoney);
            pics.Add(disCountMoney);

            UMLLayer disGiveChange = new UMLLayer("displayGiveChange", form.displayGiveChange);
            pics.Add(disGiveChange);

            UMLLayer disEventT1MoneyAdded = new UMLLayer("displayEventT1MoneyAdded", form.displayEventT1MoneyAdded);
            pics.Add(disEventT1MoneyAdded);

            UMLLayer disHoldChange = new UMLLayer("displayHoldChange", form.displayHoldChange);
            pics.Add(disHoldChange);

            UMLLayer disAfter3SecondsLeft = new UMLLayer("displayAfter3SecondsLeft", form.displayAfter3SecondsLeft);
            pics.Add(disAfter3SecondsLeft);

            UMLLayer displayYes = new UMLLayer("displayYes", form.displayYes);
            pics.Add(displayYes);

            UMLLayer disNo = new UMLLayer("displayNo", form.displayNo);
            pics.Add(disNo);

            UMLLayer disEventT2DrinkSelected = new UMLLayer("displayEventT2DrinkSelected", form.displayEventT2DrinkSelected);
            pics.Add(disEventT2DrinkSelected);

            UMLLayer disAfter3secondsRight = new UMLLayer("displayAfter3secondsRight", form.displayAfter3secondsRight);
            pics.Add(disAfter3secondsRight);

            UMLLayer displayResetMoneyTozero = new UMLLayer("displayResetMoneyTozero", form.displayResetMoneyTozero);
            pics.Add(displayResetMoneyTozero);

            UMLLayer display1EventT2ItemSelected = new UMLLayer("display1EventT2ItemSelected", form.display1EventT2ItemSelected);
            pics.Add(display1EventT2ItemSelected);

            UMLLayer display1EventT1Moneyadded = new UMLLayer("display1EventT1Moneyadded", form.display1EventT1Moneyadded);
            pics.Add(display1EventT1Moneyadded);

            UMLLayer displayEventT3ChangeButtonClicked = new UMLLayer("displayEventT3ChangeButtonClicked", form.displayEventT3ChangeButtonClicked);
            pics.Add(displayEventT3ChangeButtonClicked);

            UMLLayer displayEventT2ItemSelected = new UMLLayer("displayEventT2ItemSelected", form.displayEventT2ItemSelected);
            pics.Add(displayEventT2ItemSelected);

            UMLLayer displayChangeBackArrow = new UMLLayer("displayChangeBackArrow", form.displayChangeBackArrow);
            pics.Add(displayChangeBackArrow);

            resetToDefaultStates();


            //================== Init Timers ====================

            //init timer1
            aTimer = new System.Windows.Forms.Timer() { Interval = 1000 };
            aTimer.Tick += new EventHandler(OnTimedEvent);

            // Set the Interval to 5 seconds.
            aTimer.Interval = speed;

            //init timer
            resetArrowTimer = new System.Windows.Forms.Timer() { Interval = 1000 };
            resetArrowTimer.Tick += new EventHandler(OnResetArrowTimedEvent);

            // Set the Interval to 5 seconds.
            resetArrowTimer.Interval = speed/2;

            //init timer
            changeArrowTimer = new System.Windows.Forms.Timer() { Interval = 1000 };
            changeArrowTimer.Tick += new EventHandler(OnChangeArrowTimedEvent);

            // Set the Interval to 5 seconds.
            changeArrowTimer.Interval = speed/2;

            //init timer
            yesArrowTimer = new System.Windows.Forms.Timer() { Interval = 1000 };
            yesArrowTimer.Tick += new EventHandler(OnYesArrowTimedEvent);

            // Set the Interval to 5 seconds.
            yesArrowTimer.Interval = speed/2;

            //init timer
            noArrowTimer = new System.Windows.Forms.Timer() { Interval = 1000 };
            noArrowTimer.Tick += new EventHandler(OnNoArrowTimedEvent);

            // Set the Interval to 5 seconds.
            noArrowTimer.Interval = speed/2;

            stopWatch = new Stopwatch();
            stopWatch.Stop();
            stopWatch.Reset();

        }



        //explicit implementation of UMLDisplay.drinkSelected()
        public void drinkSelected()
        {
            aTimer.Stop();
            resetToDefaultStates();
            foreach (UMLLayer layer in pics)
            {
                int drinkFlag = vMachine.DrinkSelectedFlag;
                if (layer.Name == "displayEventT2DrinkSelected")
                {
                    layer.display();
                }

                if (layer.Name == "displayMoneyAmount")
                {
                    layer.unDisplay();
                }

                if (layer.Name == "displayItemInStock")
                {
                    layer.display();
                }
                if (layer.Name == "displayPrice")
                {
                    if (drinkFlag == 2 || drinkFlag == 3)
                    {
                        layer.display();
                    }
                }
                if (layer.Name == "displayYes")
                {
                    if (drinkFlag == 2 || drinkFlag == 3)
                    {
                        layer.display();
                        yesArrowTimer.Start();
                        yesArrow = true;
                    }
                }
                if (layer.Name == "displaySoldOut")
                {
                    if (drinkFlag == 1)
                    {
                        layer.display();
                        noArrowTimer.Start();
                        noArrow = true;
                    }
                }
                if (layer.Name == "displayNo")
                {
                    if (drinkFlag == 1)
                    {
                        layer.display();
                    }
                }
                if (layer.Name == "displayDispenseItem")
                {
                    if (drinkFlag == 2)
                    {
                        layer.display();
                    }
                }
                if (layer.Name == "displayCountMoney")
                {
                    if (drinkFlag == 2)
                    {
                        layer.unDisplay();
                    }
                }
                if (layer.Name == "displayGiveChange")
                {
                    if (drinkFlag == 2)
                    {
                        layer.display();
                        changeArrowTimer.Start();
                        changeArrow = true;
                    }
                }
                if (layer.Name == "displayEventT2ItemSelected")
                {
                    if (drinkFlag == 2)
                    {
                        layer.display();
                    }
                }

                if (layer.Name == "displayHoldChange")
                {
                    if (drinkFlag == 2)
                    {
                        layer.unDisplay();
                    }
                }
                if (layer.Name == "display1EventT2ItemSelected")
                {
                    if (drinkFlag == 2)
                    {
                        layer.display();
                        //displayResetMoneyToZero();
                        resetArrowTimer.Start();
                        resetArrow = true;
                    }
                }
            }
            aTimer.Interval = speed;

            stopWatch.Start();
            aTimer.Start();
        }

        //explicit implementation of UMLDisplay.coinInserted()
        public void coinInserted()
        {
            resetToDefaultStates();
            foreach (UMLLayer l in pics)
            {
                if (l.Name == "displayEventT1MoneyAdded")
                {
                    l.display();
                }
                if (l.Name == "display1EventT1Moneyadded")
                {
                    l.display();
                }
            }
            aTimer.Interval = speed/4;

            stopWatch.Start();
            aTimer.Start();
        }

        //explicit implementation of UMLDisplay.changeButtonClicked()
        public void changeButtonClicked()
        {
            aTimer.Stop();

            resetToDefaultStates();
            foreach (UMLLayer layer in pics)
            {
                if (layer.Name == "displayHoldChange")
                {
                    layer.unDisplay();
                }
                if (vMachine.GiveChangeEventFlag)
                {
                    if (layer.Name == "displayEventT3ChangeButtonClicked")
                    {
                        layer.display();
                    }

                }
                if (layer.Name == "displayGiveChange")
                {
                    layer.display();
                }

            }
            aTimer.Interval = speed;
            changeArrowTimer.Interval = speed / 2;
            changeArrowTimer.Start();
            
            stopWatch.Start();
            aTimer.Start();

        }


        private void OnTimedEvent(object sender, EventArgs e)
        {

            aTimer.Stop();  //stop the timer
            aTimer.Interval = speed; //reset the interval
            stopWatch.Stop();
            stopWatch.Reset();
            //reset uml to defaults
            resetToDefaultStates();

            //start the timer
            //aTimer.Enabled = true;

        }

        private void OnResetArrowTimedEvent(object sender, EventArgs e)
        {
            resetArrowTimer.Stop();
            resetArrow = false;
            stopWatch.Stop();
            stopWatch.Reset();
            resetArrowTimer.Interval = speed/2;
            foreach (UMLLayer layer in pics)
            {
                if (layer.Name == "display1EventT2ItemSelected")
                {
                    layer.unDisplay();
                }

            }
            displayResetMoneyToZero();
        }

        private void OnChangeArrowTimedEvent(object sender, EventArgs e)
        {
            changeArrowTimer.Stop();
            changeArrow = false;
            stopWatch.Stop();
            stopWatch.Reset();
            changeArrowTimer.Interval = speed/2;
            foreach (UMLLayer layer in pics)
            {
                if (layer.Name == "displayEventT3ChangeButtonClicked")
                {
                    layer.unDisplay();
                }
                if (layer.Name == "displayEventT2ItemSelected")
                {
                    layer.unDisplay();
                }
                if (layer.Name == "displayChangeBackArrow")
                {
                    layer.display();
                    changeArrow = true;
                }
            }
        }

        private void OnNoArrowTimedEvent(object sender, EventArgs e)
        {
            noArrowTimer.Stop();
            noArrow = false;
            stopWatch.Stop();
            stopWatch.Reset();
            noArrowTimer.Interval = speed/2;
            foreach (UMLLayer layer in pics)
            {
                if (layer.Name == "displayEventT2DrinkSelected")
                {
                    layer.unDisplay();
                }
                if (layer.Name == "displayItemInStock")
                {
                    layer.unDisplay();
                }
                if (layer.Name == "displayNo")
                {
                    layer.unDisplay();
                }
                if (layer.Name == "displayAfter3secondsRight")
                {
                    layer.display();
                    noArrow = true;
                }

            }
        }

        private void OnYesArrowTimedEvent(object sender, EventArgs e)
        {
            yesArrowTimer.Stop();
            yesArrow = false;
            stopWatch.Stop();
            stopWatch.Reset();
            yesArrowTimer.Interval = speed / 2;
            foreach (UMLLayer layer in pics)
            {
                if (layer.Name == "displayEventT2DrinkSelected")
                {
                    layer.unDisplay();
                }
                if (layer.Name == "displayItemInStock")
                {
                    layer.unDisplay();
                }
                if (layer.Name == "displayYes")
                {
                    layer.unDisplay();
                }
                if (layer.Name == "displayAfter3SecondsLeft")
                {
                    layer.display();
                    yesArrow = true;
                }
            }
        }


        private void resetToDefaultStates()
        {
            //reset almost all pictures
            foreach (UMLLayer layer in pics)
            {
                if ((layer.Name != "displayMoneyAmount" && layer.Name != "displayCountMoney" && layer.Name != "displayHoldChange"))
                {
                    layer.unDisplay();
                }
            }

            //return to default state
            foreach (UMLLayer layer in pics)
            {
                if (layer.Name == "displayMoneyAmount" && layer.Box.Visible == false)
                {
                    layer.display();
                }

                if (layer.Name == "displayCountMoney" && layer.Box.Visible == false)
                {
                    layer.display();
                }

                if (layer.Name == "displayHoldChange" && layer.Box.Visible == false)
                {
                    layer.display();
                }
            }

            resetArrow = false;
            changeArrow = false;
            yesArrow = false;
            noArrow = false;

        }

        private void displayResetMoneyToZero()
        {
            foreach (UMLLayer layer in pics)
            {
                if (layer.Name == "displayResetMoneyTozero")
                {
                    layer.display();
                }
            }
        }


        public void pauseTimers()
        {
            stopWatch.Stop();

            aTimer.Stop();
            resetArrowTimer.Stop();
            changeArrowTimer.Stop();
            yesArrowTimer.Stop();
            noArrowTimer.Stop();
        }

        public void startTimers()
        {
            long elapsed = stopWatch.Elapsed.Milliseconds;
            stopWatch.Reset();
            aTimer.Interval = aTimer.Interval - (int)elapsed;
            aTimer.Start();

            resetArrowTimer.Interval = speed/2 - (int)elapsed;
            if (resetArrow)
                resetArrowTimer.Start();

            changeArrowTimer.Interval = speed/2 - (int)elapsed;
            if (changeArrow)
                changeArrowTimer.Start();


            yesArrowTimer.Interval = speed/2 - (int)elapsed;
            if (yesArrow)
                yesArrowTimer.Start();

            noArrowTimer.Interval = speed/2 - (int)elapsed;
            if (noArrow)
                noArrowTimer.Start();
        }

    }
}
